#pragma once

#include <string>
#include <vector>
#include <map>
#include <memory>
#include <variant>
#include <stdexcept>

namespace El {
namespace Base {

// YAML值类型
class YamlValue {
public:
    using ValueType =
        std::variant<std::string, int, double, bool, std::vector<YamlValue>, std::map<std::string, YamlValue>>;

    YamlValue() = default;
    YamlValue(const ValueType &value) : value_(value) {}

    // 类型检查
    bool IsString() const
    {
        return std::holds_alternative<std::string>(value_);
    }
    bool IsInt() const
    {
        return std::holds_alternative<int>(value_);
    }
    bool IsDouble() const
    {
        return std::holds_alternative<double>(value_);
    }
    bool IsBool() const
    {
        return std::holds_alternative<bool>(value_);
    }
    bool IsArray() const
    {
        return std::holds_alternative<std::vector<YamlValue>>(value_);
    }
    bool IsMap() const
    {
        return std::holds_alternative<std::map<std::string, YamlValue>>(value_);
    }

    // 获取值
    std::string AsString() const
    {
        return std::get<std::string>(value_);
    }
    int AsInt() const
    {
        return std::get<int>(value_);
    }
    double AsDouble() const
    {
        return std::get<double>(value_);
    }
    bool AsBool() const
    {
        return std::get<bool>(value_);
    }
    const std::vector<YamlValue> &AsArray() const
    {
        return std::get<std::vector<YamlValue>>(value_);
    }
    const std::map<std::string, YamlValue> &AsMap() const
    {
        return std::get<std::map<std::string, YamlValue>>(value_);
    }

    // 通过路径获取值
    YamlValue Get(const std::string &path) const
    {
        if (path.empty()) {
            return *this;
        }

        if (!IsMap()) {
            throw std::runtime_error("Cannot get path from non-map value");
        }

        size_t pos = path.find('.');
        std::string key = pos == std::string::npos ? path : path.substr(0, pos);

        const auto &map = AsMap();
        auto it = map.find(key);
        if (it == map.end()) {
            throw std::runtime_error("Key not found: " + key);
        }

        if (pos == std::string::npos) {
            return it->second;
        }

        return it->second.Get(path.substr(pos + 1));
    }

private:
    ValueType value_;
};

class YamlParser {
public:
    YamlParser() = default;
    ~YamlParser() = default;

    // 从文件加载YAML
    bool LoadFromFile(const std::string &filename);

    // 从字符串加载YAML
    bool LoadFromString(const std::string &content);

    // 获取根节点
    const YamlValue &GetRoot() const
    {
        return root_;
    }

    // 通过路径获取值 (例如: "server.host" 或 "users[0].name")
    YamlValue Get(const std::string &path) const;

    // 获取错误信息
    std::string GetLastError() const
    {
        return lastError_;
    }

private:
    YamlValue root_;
    std::string lastError_;

    // 内部解析方法
    bool Parse(const std::string &content);
    YamlValue ParseValue(std::string &line);
    int GetIndentation(const std::string &line) const;
    std::pair<std::string, std::string> SplitKeyValue(const std::string &line) const;
};

} // namespace Base
} // namespace El